package de.laures.cewolf.cpp;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.DateTickUnitType;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;

import de.laures.cewolf.ChartPostProcessor;
import de.laures.cewolf.util.ChartUtils;

public class DateAxisProcessor implements ChartPostProcessor, Serializable {

	@Override
	public void processChart(Object chart, Map params) {
		JFreeChart localChart = (JFreeChart) chart;
		Plot plot = localChart.getPlot();
		List<Axis> list = new LinkedList<Axis>();
		String str = null;
		str = (String) params.get("type");
		if (str == null) {
			throw new IllegalArgumentException("type attribute could not be null");
		}
		else {
			if ("domain".equals(str)) {
				list = getPlotDomainAxis(plot);
			}
			else if ("range".equals(str)) {
				list = getPlotRangeAxis(plot);
			}
			else {
				throw new IllegalArgumentException("type attribute should be domain or range");
			}
		}

		str = (String) params.get("format");
		if (str != null) {
			DateFormat format = new SimpleDateFormat(str);
			for (Axis axis : list) {
				if (axis instanceof DateAxis) {
					DateAxis dateAxis = (DateAxis) axis;
					dateAxis.setDateFormatOverride(format);
				}
			}
		}
		String tickUnit = (String) params.get("tickUnit");
		String tickStep = (String) params.get("tickStep");
		if (tickUnit != null && tickStep != null) {
			DateTickUnitType unitType = null;
			if ("YEAR".equalsIgnoreCase(tickUnit)) {
				unitType = DateTickUnitType.YEAR;
			}
			else if ("MONTH".equalsIgnoreCase(tickUnit)) {
				unitType = DateTickUnitType.MONTH;
			}
			else if ("DAY".equalsIgnoreCase(tickUnit)) {
				unitType = DateTickUnitType.DAY;
			}
			else if ("HOUR".equalsIgnoreCase(tickUnit)) {
				unitType = DateTickUnitType.HOUR;
			}
			else if ("MINUTE".equalsIgnoreCase(tickUnit)) {
				unitType = DateTickUnitType.MINUTE;
			}
			else if ("SECOND".equalsIgnoreCase(tickUnit)) {
				unitType = DateTickUnitType.SECOND;
			}
			else if ("MILLISECOND".equalsIgnoreCase(tickUnit)) {
				unitType = DateTickUnitType.MILLISECOND;
			}
			else {
				throw new IllegalArgumentException("unknow DateTickUnitType");
			}

			for (Axis axis : list) {
				if (axis instanceof DateAxis) {
					DateAxis dateAxis = (DateAxis) axis;
					dateAxis.setTickUnit(new DateTickUnit(unitType, Integer.valueOf(tickStep)));
				}
			}
		}
		else if (tickUnit == null && tickStep == null) {

		}
		else {
			throw new IllegalArgumentException("tickUnit,tickStep should be filled both");
		}

	}

	private List<Axis> getPlotDomainAxis(Plot plot) {
		List<Axis> list = new LinkedList<Axis>();
		List<Plot> plots = ChartUtils.getPlots(plot);
		for (Plot p : plots) {
			if (p instanceof XYPlot) {
				list.add(((XYPlot) p).getDomainAxis());
			}
			else if (p instanceof CategoryPlot) {
				list.add(((CategoryPlot) p).getDomainAxis());
			}
		}
		return list;

	}

	private List<Axis> getPlotRangeAxis(Plot plot) {
		List<Axis> list = new LinkedList<Axis>();
		List<Plot> plots = ChartUtils.getPlots(plot);
		for (Plot p : plots) {
			if (p instanceof XYPlot) {
				list.add(((XYPlot) p).getRangeAxis());
			}
			else if (p instanceof CategoryPlot) {
				list.add(((CategoryPlot) p).getRangeAxis());
			}
		}
		return list;

	}

}
